package microcredit.gui.editor.loan;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Date;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import microcredit.gui.util.FormatUtilities;
import microcredit.gui.util.MDatePicker;
import microcredit.gui.util.UIUtil;
import microcredit.model.MemberToLoan;
import microcredit.model.MemberToLoanHistory;
import microcredit.model.domain.LoanExtensionReason;
import net.miginfocom.swing.MigLayout;

public class LoanExtensionPanel extends JPanel {
	private JLabel lblExtensionStart;
	private MDatePicker newStartDateChooser;
	private JLabel newWeeksLabel;
	private JSpinner newWeeksSpinner;
	private JLabel reasonLabel;
	private ExtensionReasonCombobox reasonComboBox;
	
	private final LoanGeneralForm form;
	private JTextField loanExtensionTextField;
	
	private JLabel newExtensionStartValueLabel;
	private JLabel newExtensionWeeksValueLabel;
	private JLabel descriptionLabel;
	
	private boolean editable = true;
	private boolean reasonEditable = true;
	
	public LoanExtensionPanel(LoanGeneralForm form) {
		this.form = form;
		initialize();
		initListeners();
		UIUtil.setMandatoryFields(this, MemberToLoan.NUMBER_OF_WEEKS,
				MemberToLoan.START_DATE,
				MemberToLoan.EXTENSION_REASON);
	}
	
	public boolean isEditable() {
		return editable;
	}
	
	public void setEditable(boolean editable) {
		this.editable = editable;
		getNewStartDateChooser().setVisible(editable);
		getNewWeeksSpinner().setVisible(editable);
		
		getNewExtensionStartValueLabel().setVisible(!editable);
		getNewExtensionWeeksValueLabel().setVisible(!editable);
	}
	
	public boolean isReasonEditable() {
		return reasonEditable;
	}
	
	public void setReasonEditable(boolean editable) {
		this.reasonEditable = editable;
		getReasonComboBox().setEnabled(editable);
		getLoanExtensionTextField().setEditable(editable);
		getLoanExtensionTextField().setEnabled(editable);
	}

	private void initListeners() {
		getNewWeeksSpinner().addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				form.dataChanged();
			}
		});
		getNewStartDateChooser().addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				form.dataChanged();
			}
		});
		 PropertyChangeListener listener = new PropertyChangeListener() {
		     public void propertyChange(PropertyChangeEvent e) {
		         if ("date".equals(e.getPropertyName())) {
		        	 form.dataChanged();
		         }
		     }
		 };
		 getNewStartDateChooser().addPropertyChangeListener(listener);
	}
	
	public void apply(MemberToLoan loan) {
		setVisible(loan.hasExtension());
		setEditable(!loan.isEntryFinalized() && !loan.isFinalized());
		setReasonEditable(!loan.isFinalized());
		
		MemberToLoanHistory history = loan.getLastHistory();
		if (history == null) {
			return;
		}
		Date startDate = history.getStartDate();
		Integer weeks = history.getNewNumberOfWeeks();
		LoanExtensionReason reason = history.getExtensionReason();
		String reasonText = history.getReasonText();
			
		getNewStartDateChooser().setDate(startDate);
		getReasonComboBox().setValue(reason);
		if (weeks != null) {
			getNewWeeksSpinner().setValue(weeks);
		}
		getLoanExtensionTextField().setText(reasonText);
		
		getNewExtensionStartValueLabel().setText(FormatUtilities.formatLongDate(startDate));
		getNewExtensionWeeksValueLabel().setText(weeks != null ? weeks.toString() : "");
	}
	
	public MemberToLoan receive(MemberToLoan loan) {
		MemberToLoanHistory history = loan.getLastHistory();
		if (history == null || history.getExtensionReason() == LoanExtensionReason.D) {
			return loan;
		}
		
		Date startDate = getNewStartDateChooser().getDate();
		Integer weeks = (Integer)getNewWeeksSpinner().getValue();
		LoanExtensionReason reason = getReasonComboBox().getValue();
		String reasonText = getLoanExtensionTextField().getText();
		
		history.setExtensionReason(reason);
		history.setNewNumberOfWeeks(weeks);
		history.setReasonText(reasonText);
		history.setStartDate(startDate);
		
		loan.setNumberOfWeeks(weeks);
		
		return loan;
	}
	
	private void initialize() {
		setLayout(new MigLayout("insets 0, hidemode 3", "[][][][][][][grow]", "[][][pref!][grow]"));
		add(getLblExtensionStart(), "cell 1 1");
		add(getNewStartDateChooser(), "flowx,cell 2 1,grow");
		add(getNewWeeksLabel(), "cell 5 1");
		add(getNewWeeksSpinner(), "flowx,cell 6 1");
		add(getReasonLabel(), "cell 1 2,alignx trailing,gapx 10 null");
		add(getReasonComboBox(), "cell 2 2");
		add(getDescriptionLabel(), "cell 5 2,alignx trailing");
		add(getLoanExtensionTextField(), "cell 6 2,growx");
		add(getNewExtensionStartValueLabel(), "cell 2 1");
		add(getNewExtensionWeeksValueLabel(), "cell 6 1");
	}

	private JLabel getLblExtensionStart() {
		if (lblExtensionStart == null) {
			lblExtensionStart = new JLabel("Extension start:");
		}
		return lblExtensionStart;
	}
	private MDatePicker getNewStartDateChooser() {
		if (newStartDateChooser == null) {
			newStartDateChooser = new MDatePicker();
			newStartDateChooser.setName(MemberToLoan.START_DATE);
		}
		return newStartDateChooser;
	}
	private JLabel getNewWeeksLabel() {
		if (newWeeksLabel == null) {
			newWeeksLabel = new JLabel("No of weeks:");
		}
		return newWeeksLabel;
	}
	private JSpinner getNewWeeksSpinner() {
		if (newWeeksSpinner == null) {
			newWeeksSpinner = new JSpinner();
			newWeeksSpinner.setModel(new SpinnerNumberModel(0, 0, 200, 1));
			newWeeksSpinner.setName(MemberToLoan.NUMBER_OF_WEEKS);
		}
		return newWeeksSpinner;
	}
	private JLabel getReasonLabel() {
		if (reasonLabel == null) {
			reasonLabel = new JLabel("Reason:");
		}
		return reasonLabel;
	}
	private ExtensionReasonCombobox getReasonComboBox() {
		if (reasonComboBox == null) {
			reasonComboBox = new ExtensionReasonCombobox();
			reasonComboBox.setName(MemberToLoan.EXTENSION_REASON);
			reasonComboBox.enableAutocompletion();
		}
		return reasonComboBox;
	}
	private JTextField getLoanExtensionTextField() {
		if (loanExtensionTextField == null) {
			loanExtensionTextField = new JTextField();
			loanExtensionTextField.setColumns(10);
			loanExtensionTextField.setName(MemberToLoan.EXTENSION_DESCRIPTION);
		}
		return loanExtensionTextField;
	}
	private JLabel getNewExtensionStartValueLabel() {
		if (newExtensionStartValueLabel == null) {
			newExtensionStartValueLabel = new JLabel("23.12.1973");
		}
		return newExtensionStartValueLabel;
	}
	private JLabel getNewExtensionWeeksValueLabel() {
		if (newExtensionWeeksValueLabel == null) {
			newExtensionWeeksValueLabel = new JLabel("13");
		}
		return newExtensionWeeksValueLabel;
	}
	private JLabel getDescriptionLabel() {
		if (descriptionLabel == null) {
			descriptionLabel = new JLabel("Description:");
		}
		return descriptionLabel;
	}

	public void focusDefault() {
		if (isEditable()) {
			getNewWeeksSpinner().requestFocus();
		} else if (isReasonEditable()) {
			getReasonComboBox().requestFocus();
		}
	}
}

